package util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * jackson 工具类
 *
 * @author zhangjian
 * @version 1.0.0
 * @since 2021/09/21 15:19
 */
public class JacksonUtil {

  public static final ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());
  static {
    // 反序列化时忽略不存在的JavaBean属性:
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
  }

  /** 工具类不允许外界创建对象 */
  private JacksonUtil() {
  }

  /**
   * 嵌套 JSONString 转 Map<String, String>
   */
  public static HashMap<String, String> parseJsonNode(String json) throws JsonProcessingException {
    HashMap<String, String> map = new HashMap<>();
    JsonNode jsonNode = mapper.readTree(json);
    parseJsonNode(jsonNode, map, "");
    return map;
  }

  private static void parseJsonNode(JsonNode jsonNode, Map<String, String> map, String key) {
    JsonNodeType nodeType = jsonNode.getNodeType();
    // 数组
    if (nodeType == JsonNodeType.ARRAY) {
      Iterator<JsonNode> elements = jsonNode.elements();
      int i = 0;
      while (elements.hasNext()) {
        parseJsonNode(elements.next(), map, key + String.format("[%d]", i++));
      }
    }
    // 对象
    else if (nodeType == JsonNodeType.OBJECT) {
      Iterator<Map.Entry<String, JsonNode>> fields = jsonNode.fields();
      while (fields.hasNext()) {
        Map.Entry<String, JsonNode> field = fields.next();
        parseJsonNode(field.getValue(), map, key + "." + field.getKey());
      }
    }
    // 数字 / 字符串
    else if(nodeType == JsonNodeType.NUMBER || nodeType == JsonNodeType.STRING){
      map.put(key, jsonNode.textValue());
    }else {
      throw new UnsupportedOperationException("unknown JsonNodeType");
    }
  }

  public static <T> T jsonToObject(String json, Class<T> t) throws JsonProcessingException {
    return mapper.readValue(json, t);
  }

  public static String objectToString(Object obj) throws JsonProcessingException {
    return mapper.writeValueAsString(obj);
  }

}
